package cn.ug.member.service.impl;

import cn.ug.member.mapper.MemberGroupMapper;
import cn.ug.member.mapper.MemberGroupRecordMapper;
import cn.ug.member.mapper.MemberGroupStatisticsMapper;
import cn.ug.member.mapper.MemberUserMapper;
import cn.ug.member.mapper.entity.MemberGroup;
import cn.ug.member.mapper.entity.MemberGroupRecord;
import cn.ug.member.mapper.entity.MemberGroupStatistics;
import cn.ug.member.mapper.entity.MemberUser;
import cn.ug.member.service.MemberGroupService;
import cn.ug.util.UF;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

@Service
public class MemberGroupServiceImpl implements MemberGroupService {
    private static Logger logger = LoggerFactory.getLogger(MemberGroupServiceImpl.class);
    private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(2, new ThreadFactory(){
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setDaemon(true);
            return t;
        }
    });

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                if (EXECUTOR_SERVICE != null) {
                    EXECUTOR_SERVICE.shutdown();
                }
            }
        });
    }
    @Autowired
    private MemberGroupMapper memberGroupMapper;
    @Autowired
    private MemberGroupStatisticsMapper memberGroupStatisticsMapper;
    @Autowired
    private MemberGroupRecordMapper memberGroupRecordMapper;
    @Autowired
    private MemberUserMapper memberUserMapper;

    @Override
    public List<MemberGroup> query(String name, String startTime, String endTime, String order, String sort, int offset, int size) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startTime)) {
            params.put("startTime", startTime);
        }
        if (StringUtils.isNotBlank(endTime)) {
            params.put("endTime", endTime);
        }
        List<String> orders = Arrays.asList("add_time", "persons", "modify_time");
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }
        return memberGroupMapper.query(params);
    }

    @Override
    public int count(String name, String startTime, String endTime) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(startTime)) {
            params.put("startTime", startTime);
        }
        if (StringUtils.isNotBlank(endTime)) {
            params.put("endTime", endTime);
        }
        return memberGroupMapper.count(params);
    }

    @Override
    public int getGroupId(String memberId, List<Integer> groupIds) {
        if (StringUtils.isNotBlank(memberId) && groupIds != null && groupIds.size() > 0) {
            MemberUser memberUser = memberUserMapper.findById(memberId);
            if (memberUser == null) {
                return 0;
            }
            int type = 1;
            if (StringUtils.isNotBlank(memberUser.getIdCard())) {
                type = 2;
                int num = memberGroupMapper.countMemberTradeNum(memberId);
                if (num > 0) {
                    type = 3;
                }
            }
            List<MemberGroup> memberGroups =  memberGroupMapper.queryForEnabledList(-1);
            if (memberGroups == null || memberGroups.size() == 0) {
                return 0;
            }
            int defaultGroupId = 0;
            MemberGroup memberGroup = null;
            for (MemberGroup group : memberGroups) {
                if (!groupIds.contains(group.getId())) {
                    continue;
                }
                if (group.getType() == 1) {
                    if (type == group.getLabelCategory()) {
                        defaultGroupId = group.getId();
                    }
                } else {
                    if (type == group.getLabelCategory()) {
                        if (type == 1) {
                            Map<String, Object> params = new HashMap<String, Object>();
                            if (StringUtils.isNotBlank(group.getChannelId())) {
                                params.put("channelId", group.getChannelId());
                            }
                            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                                params.put("startTime", group.getStartTime());
                                params.put("endTime", group.getEndTime());
                            }
                            params.put("memberId", memberId);
                            int num = memberGroupMapper.countRegisterAndNotBindCardNum(params);
                            if (num > 0) {
                                memberGroup = group;
                            }
                        } else if (type == 2) {
                            Map<String, Object> params = new HashMap<String, Object>();
                            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                                params.put("startTime", group.getStartTime());
                                params.put("endTime", group.getEndTime());
                            }
                            params.put("memberId", memberId);
                            int num = memberGroupMapper.countBindCardAndNotTradeNum(params);
                            if (num > 0) {
                                memberGroup = group;
                            }
                        } else if (type == 3) {
                            Map<String, Object> params = new HashMap<String, Object>();
                            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                                params.put("startTime", group.getStartTime());
                                params.put("endTime", group.getEndTime());
                            }
                            params.put("investmentMark", group.getInvestmentMark());
                            params.put("startInvestmentAmount", group.getStartInvestmentAmount());
                            params.put("endInvestmentAmount", group.getEndInvestmentAmount());

                            params.put("leasebackMark", group.getLeasebackMark());
                            params.put("startLeasebackNum", group.getStartLeasebackNum());
                            params.put("endLeasebackNum", group.getEndLeasebackNum());
                            if (StringUtils.isNotBlank(group.getStartLeasebackTime()) && StringUtils.isNotBlank(group.getEndLeasebackTime())) {
                                params.put("startLeasebackTime", group.getStartLeasebackTime());
                                params.put("endLeasebackTime", group.getEndLeasebackTime());
                            }
                            params.put("memberId", memberId);
                            int num = memberGroupMapper.countTradeNum(params);
                            if (num > 0) {
                                memberGroup = group;
                            }
                        }
                    }
                }
            }
            if (memberGroup != null && memberGroup.getId() > 0) {
                return memberGroup.getId();
            }
            return defaultGroupId;
        }
        return 0;
    }

    @Override
    public void execute(MemberGroup group) {
        if (group.getLabelCategory() == 1) {
            Map<String, Object> params = new HashMap<String, Object>();
            if (StringUtils.isNotBlank(group.getChannelId())) {
                params.put("channelId", group.getChannelId());
            }
            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                params.put("startTime", group.getStartTime());
                params.put("endTime", group.getEndTime());
            }
            int num = memberGroupMapper.countRegisterAndNotBindCardNum(params);
            group.setPersons(num);
            group.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
            if (save(group)) {
                MemberGroupStatistics memberGroupStatistics = new MemberGroupStatistics();
                memberGroupStatistics.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                memberGroupStatistics.setGroupId(group.getId());
                memberGroupStatistics.setPersons(num);
                memberGroupStatisticsMapper.insert(memberGroupStatistics);
                params.put("groupId", group.getId());
                memberGroupRecordMapper.insertForRegisterUsers(params);
            }
        } else if (group.getLabelCategory() == 2) {
            Map<String, Object> params = new HashMap<String, Object>();
            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                params.put("startTime", group.getStartTime());
                params.put("endTime", group.getEndTime());
            }
            int num = memberGroupMapper.countBindCardAndNotTradeNum(params);
            group.setPersons(num);
            group.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
            if (save(group)) {
                MemberGroupStatistics memberGroupStatistics = new MemberGroupStatistics();
                memberGroupStatistics.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                memberGroupStatistics.setGroupId(group.getId());
                memberGroupStatistics.setPersons(num);
                memberGroupStatisticsMapper.insert(memberGroupStatistics);
                params.put("groupId", group.getId());
                memberGroupRecordMapper.insertForBindCardUsers(params);
            }
        } else if (group.getLabelCategory() == 3) {
            Map<String, Object> params = new HashMap<String, Object>();
            if (StringUtils.isNotBlank(group.getStartTime()) && StringUtils.isNotBlank(group.getEndTime())) {
                params.put("startTime", group.getStartTime());
                params.put("endTime", group.getEndTime());
            }
            params.put("investmentMark", group.getInvestmentMark());
            params.put("startInvestmentAmount", group.getStartInvestmentAmount());
            params.put("endInvestmentAmount", group.getEndInvestmentAmount());

            params.put("leasebackMark", group.getLeasebackMark());
            params.put("startLeasebackNum", group.getStartLeasebackNum());
            params.put("endLeasebackNum", group.getEndLeasebackNum());
            if (StringUtils.isNotBlank(group.getStartLeasebackTime()) && StringUtils.isNotBlank(group.getEndLeasebackTime())) {
                params.put("startLeasebackTime", group.getStartLeasebackTime());
                params.put("endLeasebackTime", group.getEndLeasebackTime());
            }
            int num = memberGroupMapper.countTradeNum(params);
            group.setPersons(num);
            group.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
            if (save(group)) {
                MemberGroupStatistics memberGroupStatistics = new MemberGroupStatistics();
                memberGroupStatistics.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                memberGroupStatistics.setGroupId(group.getId());
                memberGroupStatistics.setPersons(num);
                memberGroupStatisticsMapper.insert(memberGroupStatistics);
                params.put("groupId", group.getId());
                memberGroupRecordMapper.insertForTradeAndLeasebackUsers(params);
            }
        }
    }

    @Override
    public boolean save(MemberGroup memberGroup) {
        if (memberGroup != null) {
            if (memberGroup.getId() > 0) {
                return memberGroupMapper.update(memberGroup) > 0 ? true : false;
             } else {
                memberGroup.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                return memberGroupMapper.insert(memberGroup) > 0 ? true : false;
            }
        }
        return false;
    }

    @Override
    public MemberGroup findById(int id) {
        if (id > 0) {
            return memberGroupMapper.findById(id);
        }
        return null;
    }

    @Override
    public boolean updateStatus(int id, int status) {
        if (id > 0 && (status == 1 || status == 2)) {
            logger.info("更改用户群组状态...");
            boolean result = memberGroupMapper.updateStatus(id, status) > 0 ? true : false;
            if (result && status == 2) {
                MemberGroup memberGroup = memberGroupMapper.findById(id);
                if (memberGroup != null && memberGroup.getCalculationCategory() == 2) {
                    EXECUTOR_SERVICE.execute(new Runnable() {
                        @Override
                        public void run() {
                            logger.info("执行单次计算...");
                            execute(memberGroup);
                        }
                    });
                }
            }
            return result;
        }
        return false;
    }

    @Override
    public boolean delete(int id) {
        if (id > 0) {
            return memberGroupMapper.delete(id) > 0 ? true : false;
        }
        return false;
    }

    @Override
    public List<MemberGroup> queryForEnabledList(int type) {
        return memberGroupMapper.queryForEnabledList(type);
    }

    @Override
    public List<MemberGroupStatistics> query(int groupId, int startNum, int endNum, String startTime, String endTime, String order, String sort, int offset, int size) {
        if (groupId > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("groupId", groupId);
            params.put("startNum", startNum);
            params.put("endNum", endNum);
            if (StringUtils.isNotBlank(startTime)) {
                params.put("startTime", startTime);
            }
            if (StringUtils.isNotBlank(endTime)) {
                params.put("endTime", endTime);
            }
            List<String> orders = Arrays.asList("add_time", "persons");
            if (orders.contains(order)) {
                params.put("order", order);
                params.put("sort", "desc");
                if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                    params.put("sort", sort);
                }
            }
            return memberGroupStatisticsMapper.query(params);
        }
        return null;
    }

    @Override
    public int count(int groupId, int startNum, int endNum, String startTime, String endTime) {
        if (groupId > 0) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("groupId", groupId);
            params.put("startNum", startNum);
            params.put("endNum", endNum);
            if (StringUtils.isNotBlank(startTime)) {
                params.put("startTime", startTime);
            }
            if (StringUtils.isNotBlank(endTime)) {
                params.put("endTime", endTime);
            }
            return memberGroupStatisticsMapper.count(params);
        }
        return 0;
    }

    @Override
    public List<MemberGroupRecord> query(int groupId, String calculationDate) {
        if (groupId > 0 && StringUtils.isNotBlank(calculationDate)) {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("groupId", groupId);
            params.put("calculationDate", calculationDate);
            return memberGroupRecordMapper.query(params);
        }
        return null;
    }

    @Override
    public int countRegisterAndNotBindCardNum(Map<String, Object> params) {
        return memberGroupMapper.countRegisterAndNotBindCardNum(params);
    }

    @Override
    public int countBindCardAndNotTradeNum(Map<String, Object> params) {
        return memberGroupMapper.countBindCardAndNotTradeNum(params);
    }

    @Override
    public int countTradeNum(Map<String, Object> params) {
        return memberGroupMapper.countTradeNum(params);
    }
}
